#include "Server.h"

Server::Server()
{
#ifdef WIN32
	if (WSAStartup(MAKEWORD(2,2), &_wsa))
	{
		std::cerr << "Error: can't initialise WSA." << std::endl;
		exit(EXIT_FAILURE);
	}
#endif
	_socket = socket(AF_INET, SOCK_DGRAM, 0);
	if (_socket == INVALID_SOCKET)
	{
		std::cerr << "Error: can't create socket." << std::endl;
		exit(EXIT_FAILURE);
	}
	_saddr.sin_family = AF_INET;
	_saddr.sin_addr.s_addr = INADDR_ANY;  
	_saddr.sin_port = htons(ServerData::port);
	if (bind(_socket, (struct sockaddr*)&_saddr, sizeof(_saddr)))
	{
		std::cerr << "Error: can't bind on socket " << _socket << std::endl;
		exit(EXIT_FAILURE);
	}
}

Server::~Server()
{
	std::cout << "Stopping receive and send threads..." << std::flush;
	_recv.stop();
	_send.stop();
	std::cout << " done." << std::endl;
	std::cout << "Clearing game list..." << std::flush;
	_gl.clear();
	std::cout << " done." << std::endl;
	std::cout << "Clearing connection list..." << std::flush;
	_cl.clear();
	std::cout << " done." << std::endl;
	std::cout << "Closing server socket..." << std::flush;
	closesocket(_socket);
	std::cout << " done." << std::endl;
}

void	Server::run()
{
	Network::Data	recvData(_socket, &_saddr, &_recvList, &_cl);
	Network::Data	sendData(_socket, &_saddr, &_sendList, &_cl);

	std::cout << "Server has started on port " << ntohs(_saddr.sin_port) << "." << std::endl;
	std::cout << "Listening on socket " << _socket << "." << std::endl;
	std::cout << "Creating receiving and sending threads..." << std::flush;
	_recv.start(&recvData);
	_send.start(&sendData);
	std::cout << " done." << std::endl;
	std::cout << "Now ready to run ! :)" << std::endl;
	loop();
}

void	Server::loop()
{
	_run = true;
	while (_run)
	{
		checkRecvList();
	}
}

void	Server::checkRecvList()
{
	if (_recvList.size() > 0)
	{
		std::string			ip, msg;
		unsigned int		port, size;
		std::istringstream	iss(_recvList.front());
		Connection*			c;

		iss >> ip >> port >> size >> msg;
		std::cout << "Received from " << ip << ":" << port << " => " << msg << std::endl;
		if ((c = getConnection(ip, port)))
		{
			std::cout << "Client found." << std::endl;
		}
		else
		{
			c = new Connection(ip, port);
			std::cout << "\tNew client, adding to clients list." << std::endl;
			_cl.push_back(c);
		}
		_recvList.pop_front();
	}
}

Connection*	Server::getConnection(std::string ip, unsigned int port) const
{
	std::list<Connection*>::const_iterator	it = _cl.begin();

	for (; it != _cl.end(); ++it)
	{
		if ((*it)->getHostname() == ip && (*it)->getPort() == port)
			return (*it);
	}
	return (NULL);
}
